package mainClasses;

import pieces.*;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.soap.Node;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

@SuppressWarnings("unused")

public class GraphicalKnightsTour extends JPanel implements BoardGame{
	/**
	 * Size of the board (constant)
	 */
	private static final int SIZE = 8;
	
	/**
	 * Instance of the board that is used during the Knight's Tour Game
	 */
	private Board board1;		
	
	/**
	 * Dimension of the window of the game
	 */
	Dimension d = new Dimension(800, 700);
	
	/**
	 * A 2D array of booleans that are set to true if the corresponding cell on the board has been visited by the 
	 * knight during the Knight's Tour Game
	 */
	Boolean[][] visited;
	
	/**
	 * A 2D array of buttons used to represent the clickable cells of the board
	 */
	JButton[][] buttons;
	
	/**
	 * The instance of Knight that is moved around the board during the Knight's Tour Game
	 */
	Knight knight;
	
	/**
	 * All the moves made so far
	 */
	ArrayList<Point> allMoves = new ArrayList<Point>();
	
	/**
	 * Instance of InputAndOutput that is used to input and output error and feedback messages to the player
	 */
	InputAndOutput io;
	
	public int moveNumber = 0;
	public int moveNumberRedo = 0;
	ArrayList<Knight> knightsUndo = new ArrayList<Knight>();
	ArrayList<Boolean[][]> visitedUndo = new ArrayList<Boolean[][]>();
	ArrayList<Board> boardsUndo = new ArrayList<Board>();
	ArrayList<Integer> ioUndo = new ArrayList<Integer>();
	ArrayList<ArrayList<Point>> allMovesUndo = new ArrayList<ArrayList<Point>>();
	
	ArrayList<Knight> knightsRedo = new ArrayList<Knight>();
	ArrayList<Boolean[][]> visitedRedo = new ArrayList<Boolean[][]>();
	ArrayList<Board> boardsRedo = new ArrayList<Board>();
	ArrayList<Integer> ioRedo = new ArrayList<Integer>();
	ArrayList<ArrayList<Point>> allMovesRedo = new ArrayList<ArrayList<Point>>();
	
	JButton no = new JButton("No");
	JButton yes = new JButton("Yes");
	JButton yesAndNo[];

	/**
	 * Constructor for the GraphicalKnightsTour game. It initializes the JPanel, buttons and visited. The buttons 
	 * are initialized to a 2D array of Buttons and this (the instance of this class) is added as an action listener 
	 * to each of the buttons so when a button is clicked, the game behaves appropriately. The visited is initialized
	 * a 2D array of boolean that is initially set to false to indicate that the cells have not been visited by the
	 * knight. A knight is created an placed at the top right corner of the board.
	 * @throws IOException 
	 * 
	 */
	public GraphicalKnightsTour(InputAndOutput io)
	{
		this.setSize(d);
		this.setLayout(new GridLayout(SIZE, SIZE));
		this.board1 = new Board();
		this.io = io;
		
		
		this.yesAndNo = new JButton[2];
		this.yesAndNo[0] = this.yes;
		this.yesAndNo[1] = this.no;
		this.yes.addActionListener(this);
		this.no.addActionListener(this);
		

		this.io.setMode(InputAndOutput.LABEL);
		this.io.setOutputField("Welcome to Knight Tour game.");
		this.io.setOutputField("Click on the block you would like to move to.");
		
		
		buttons = new JButton[SIZE][SIZE];
		visited = new Boolean[SIZE][SIZE];
		for (int i = SIZE-1; i >= 0; i--) 
		{
			for (int j = 0; j < SIZE; j++) 
			{
				JButton b = new JButton();
				b.addActionListener(this);
				buttons[i][j]=b;
				this.add(b);
				visited[i][j] = false;
				
			}
		}
		
		knight = new Knight(7, 0, board1, "White");
		visited[7][0] = true;
		allMoves.add(new Point(knight.getX(), knight.getY()));
		board1.add(knight);
		this.print();
		this.setVisible(true);
	}
	
	
	
	/**
     * Responds to button presses on the chess board and acts accordingly
     * 
     * @param e - An event that is created when a button is pressed
     */
	public void actionPerformed(ActionEvent e) {
		if(e.getSource()==yes)
		{
			this.restart();
			this.io.setMode(InputAndOutput.LABEL);
			this.io.setOutputField(" ");
			this.io.setVisible(true);
		}
		else if(e.getSource()==no)
		{
			System.exit(0);
		}
		else
		{
			for (int i = 0; i < SIZE; i++) 
	        {
	            for (int j = 0; j < SIZE; j++) 
	            {
	                if(e.getSource()==buttons[i][j])
	                {
						if(!visited[i][j])
						{
							if(knight.movePossible(i, j))
							{
								this.saveCurrentState();
								this.moveNumber++;
								this.boardsRedo = new ArrayList<Board>();
								this.knightsRedo = new ArrayList<Knight>();
								this.visitedRedo  = new ArrayList<Boolean[][]>();
								this.allMovesRedo = new ArrayList<ArrayList<Point>>();
								this.moveNumberRedo = 0;
								knight.moveKnight(i, j);
								knight.changePosition(i, j);
								allMoves.add(new Point(knight.getX(), knight.getY()));
								this.visited[i][j] = true;
								this.print();
								
								if(this.won())
								{
									this.io.setMode(InputAndOutput.LABEL_AND_BUTTONS);
									this.io.addButtons(yesAndNo);
									this.io.setOutputField(" ");
									this.io.setOutputField("Congratulations, you won! Play again?");
									this.io.setVisible(true);
									for (int x = SIZE-1; x >= 0; x--) 
									{
										for (int y = 0; y < SIZE; y++)
										{buttons[x][y].setBackground(Color.white);}
									}
								}
								else if(!(this.hasMoves())){
									this.io.setMode(InputAndOutput.LABEL_AND_BUTTONS);
									this.io.addButtons(yesAndNo);
									this.io.setOutputField("You are trapped! Play again?");
									this.io.setVisible(true);
									
								}
							}
							else
							{
								this.io.setOutputField("Can't get there!");
								this.io.setOutputField("Please choose another spot");

							}
						}
						else
						{
							this.io.setOutputField("That spot has already been visited!");
							this.io.setOutputField("Please choose another spot");

						}
	                }
	            }
			}
		}
	}
	
	
	
	
	
	/**
	* Loads the current state of the board from a chessxml file
	* It sets the appropriate instance variables to allow the user to continue
	* the game using the saved settings
	*/
	public void load()
	{
		String fileName = "temp";
		File file = new File(fileName);
		JFileChooser chooseFile = new JFileChooser();
		chooseFile.showOpenDialog(chooseFile);
		file = chooseFile.getSelectedFile();
		
		if(file!=null){
			fileName = file.getAbsolutePath();
			if(!fileName.endsWith(".chessxml")) //If the selected file is invalid
			{
				this.io.setOutputField("You have selected an invalid file");
				return;
			}
	    	
		}
		else{fileName = null;}
		
		if(fileName!=null)
		{
			this.restart();
			try {
	            DocumentBuilderFactory documentBuilder = DocumentBuilderFactory.newInstance();
	            DocumentBuilder docBuild = documentBuilder.newDocumentBuilder();
	            Document doc = docBuild.parse (new File(fileName));
	            doc.getDocumentElement ().normalize ();
	            NodeList ListOfVisit = doc.getElementsByTagName("visited");
	            int totalQueens = ListOfVisit.getLength();
	            for(int s=0; s<ListOfVisit.getLength() ; s++)
	            {
	                org.w3c.dom.Node firstVisiteNode = ListOfVisit.item(s);
	                if(firstVisiteNode.getNodeType() == Node.ELEMENT_NODE){
	                	org.w3c.dom.Element xElements = (org.w3c.dom.Element)firstVisiteNode;
	                	org.w3c.dom.NodeList xList = xElements.getElementsByTagName("x");
	                    org.w3c.dom.Element xFinal = (org.w3c.dom.Element)xList.item(0);
	                    
	                    org.w3c.dom.NodeList xNode = xFinal.getChildNodes();
	                    
	                    org.w3c.dom.NodeList yList = xElements.getElementsByTagName("y");
	                    org.w3c.dom.Element yFinal = (org.w3c.dom.Element)yList.item(0);
	                    org.w3c.dom.NodeList yNode = yFinal.getChildNodes();
	                    
	                    org.w3c.dom.NodeList kinghtList = xElements.getElementsByTagName("knight");
	                    org.w3c.dom.Element knightFinal = (org.w3c.dom.Element)kinghtList.item(0);
	                    org.w3c.dom.NodeList knightNode = knightFinal.getChildNodes();
	                    
	                    org.w3c.dom.NodeList visitList = xElements.getElementsByTagName("visit");
	                    org.w3c.dom.Element visitFinal = (org.w3c.dom.Element)visitList.item(0);
	                    org.w3c.dom.NodeList visitNode = visitFinal.getChildNodes();
	                    
	                    String xString = ((org.w3c.dom.Node)xNode.item(0)).getNodeValue().trim();
	                    String yString = ((org.w3c.dom.Node)yNode.item(0)).getNodeValue().trim();
	                    String knightString = ((org.w3c.dom.Node)knightNode.item(0)).getNodeValue().trim();
	                    String visitString = ((org.w3c.dom.Node)visitNode.item(0)).getNodeValue().trim();
	                    int xaxis = xString.charAt(0)-48;
	                    int yaxis = yString.charAt(0)-48;
	                    if(s!=0)
	                    {
	                    	this.saveCurrentState();
							this.moveNumber++;
							this.boardsRedo = new ArrayList<Board>();
							this.knightsRedo = new ArrayList<Knight>();
							this.visitedRedo  = new ArrayList<Boolean[][]>();
							this.allMovesRedo = new ArrayList<ArrayList<Point>>();
							this.moveNumberRedo = 0;
							knight.moveKnight(xaxis, yaxis);
							knight.changePosition(xaxis, yaxis);
							allMoves.add(new Point(knight.getX(), knight.getY()));
							this.visited[xaxis][yaxis] = true;
							this.print();
							
							if(this.won())
							{
								this.io.setMode(InputAndOutput.LABEL_AND_BUTTONS);
								this.io.addButtons(yesAndNo);
								this.io.setOutputField(" ");
								this.io.setOutputField("Congratulations, you won! Play again?");
								this.io.setVisible(true);
								for (int x = SIZE-1; x >= 0; x--) 
								{
									for (int y = 0; y < SIZE; y++)
									{buttons[x][y].setBackground(Color.white);}
								}
							}
							else if(!(this.hasMoves())){
								this.io.setMode(InputAndOutput.LABEL_AND_BUTTONS);
								this.io.addButtons(yesAndNo);
								this.io.setOutputField("You are trapped! Play again?");
								this.io.setVisible(true);
								
							}
	                    }
	                }
	            }
	        }catch (SAXParseException err) {
	        System.out.println ("** Parsing error" + ", line " + err.getLineNumber () + ", uri " + err.getSystemId ());
	        System.out.println(" " + err.getMessage ());
	
	        }catch(FileNotFoundException fnfe)
	        {
	        	JOptionPane.showMessageDialog(this, "Cannot find a saved game in this file: ", "File not found warning", JOptionPane.INFORMATION_MESSAGE, null);
	        }catch (SAXException e) {
	        Exception x = e.getException ();
	        ((x == null) ? e : x).printStackTrace ();
	
	        }catch (Throwable t) {
	        t.printStackTrace ();
	        }
		}
	}
	
	
	/**
     * Saves the current state of the game into a chessxml file
     * @throws IOException
     */
	public void save() throws IOException 
	{
		String s = "";
		s += "<knightTour>";
		for(int d=0; d<this.allMoves.size(); d++)
		{
			int i = (int) this.allMoves.get(d).getX();
			int j = (int) this.allMoves.get(d).getY();
			s += "<visited>";
			s +="<x>" + i + "</x>";
			s +="<y>" + j + "</y>";
			if(this.knight.getX()==i && this.knight.getX()==j)
			{
				s += "<knight>";
				s += "1";
				s += "</knight>";
			}else
			{
				s += "<knight>";
				s += "0";
				s += "</knight>";
			}
			s += "<visit>";
			if(this.visited[i][j])
			{
				s += "1";
			}else
			{
				s += "0";
			}
			s += "</visit>";
			s += "</visited>";
		}
		s+= "</knightTour>";
		this.writeToFile(s);
	}
	
	
	/**
     * Writes the current state of the board into an chessxml file for save and load functions
     * @param s The string that represents the current state of the board
     * @throws IOException
     */
	public void writeToFile(String s) throws IOException 
	{
		String fileName = "temp";
		File file = new File(fileName);
		JFileChooser chooseFile = new JFileChooser();
		chooseFile.showSaveDialog(chooseFile);
		file = chooseFile.getSelectedFile();
		
		if(file!=null){
			fileName = file.getAbsolutePath()+ ".chessxml";
		}
		else{fileName = null;}
		if(fileName!=null)
		{
			FileOutputStream out = new FileOutputStream(fileName);
		 try {
				 byte[] b = s.getBytes();
				 out.write(b, 0, s.length());
	      	} finally {
		        out.close();
	      }
		}
    }
	
	
	/**
	 * Saves the current state of the board to be used in the undo and redo functions
	 */
	public void saveCurrentState()
	{
		if(moveNumber<0)
		{
			moveNumber = 0;
		}
		Board b = this.board1.createBoard();
		this.boardsUndo.add(this.moveNumber, b);
		Knight temp = this.knight;
		Knight currentknight = new Knight(temp.getX(), temp.getY(), b, temp.getSide());
		this.knightsUndo.add(this.moveNumber, currentknight);
		Boolean[][] currentvisited = new Boolean[GraphicalKnightsTour.SIZE][GraphicalKnightsTour.SIZE];
		for (int i = SIZE-1; i >= 0; i--) 
		{
			for (int j = 0; j < SIZE; j++) 
			{
				boolean bool = this.visited[i][j].booleanValue();
				Boolean tempBoolean = new Boolean(bool);
				currentvisited[i][j] = tempBoolean;
			}
		}
		this.visitedUndo.add(this.moveNumber, currentvisited);
		InputAndOutput currentIO = new InputAndOutput();
		int modenum = this.io.mode;
		Integer integer = new Integer(modenum);
		this.ioUndo.add(this.moveNumber, integer);
		
		ArrayList<Point> movesmade = new ArrayList<Point>();
		ArrayList<Point> tempArray = this.allMoves;
		for(int k = 0; k<tempArray.size(); k++)
		{
			int x = (int) tempArray.get(k).getX();
			int y = (int) tempArray.get(k).getY();
			Point point = new Point(x, y);
			movesmade.add(point);
		}
		this.allMovesUndo.add(this.moveNumber, movesmade);
	}
	
	
	/**
	 * Prints the board by coloring the buttons and setting the appropriate
	 * icon for the knight's poisition. The visited spots on the board are
	 * colored red
	 */
	public void print()
	{
		for (int i = SIZE-1; i >= 0; i--) 
		{
			for (int j = 0; j < SIZE; j++) 
			{
				if((i+j)%2 == 0)
				{
					buttons[i][j].setBackground(new Color(70, 5, 3));
					if(this.visited[i][j])
					{
						buttons[i][j].setBackground(new Color(255, 0, 0));
					}
				}else
				{
					buttons[i][j].setBackground(Color.white);
					if(this.visited[i][j])
					{
						buttons[i][j].setBackground(new Color(255, 0, 0));
					}
				}
				
				if(this.board1.getPiece(i, j) instanceof NullPiece)
				{
					buttons[i][j].setIcon(new ImageIcon("WHITENULL.GIF"));
				}else if(this.board1.getPiece(i, j) instanceof Knight && this.board1.getPiece(i, j).getSide().equals("White"))
				{
					buttons[i][j].setIcon(new ImageIcon("KNIGHT2.PNG"));
				}else if(this.board1.getPiece(i, j) instanceof Knight && this.board1.getPiece(i, j).getSide().equals("Black"))
				{
					buttons[i][j].setIcon(new ImageIcon("Ba-KNIGHT-W.PNG"));
				}
			}
		}
		this.setVisible(true);
	}

	
	
	
	/**
     * check if any of the item on the array is false and if it is then return false.
     * if all the items are true then return true.
     * @param bool - 2d array of boolean to represent the all coordinate on a board.
     * @return Boolean set to true if KNIGHT TOUR is a win

     */
	private boolean won()
	{
		for(int x=0; x<SIZE; x++)
		{
			for(int y=0; y<SIZE; y++)
			{
				if(visited[x][y]==false)
				{
					return false;
				}
			}
		}
		return true;
	}
	
	
	
	/**
	 * Returns true if the knight has possible moves on the board
	 * @return A boolean set to true if the knight has atleast one possible move
	 */
	private boolean hasMoves(){
		int currentPosX = this.knight.getX();
		int currentPosY = this.knight.getY();
		int minX = currentPosX-2;
		int minY = currentPosY-2;
		int maxX = currentPosX+2;
		int maxY = currentPosY+2;
		
		if(minX < 0){minX = 0;}
		if(minY < 0){minY = 0;}
		if(maxX > 7){maxX = 7;}
		if(maxY > 7){maxY = 7;}
		
		for(int i=minX; i<= maxX; i++){
			for(int j=minY; j<= maxY; j++){
				if(!visited[i][j]){
					if(this.knight.movePossible(i, j)){

						return true;
					}
					
				}
			}
		}
		return false;
	}
	
	
	
	
	/**
	 * Restart the game by resetting the instance variables to their original states
	 */
	public void restart()
	{
		this.moveNumber = 0;
		this.moveNumberRedo = 0;
		this.knightsUndo = new ArrayList<Knight>();
		this.visitedUndo = new ArrayList<Boolean[][]>();
		this.boardsUndo = new ArrayList<Board>();
		this.ioUndo = new ArrayList<Integer>();
		this.allMovesUndo = new ArrayList<ArrayList<Point>>();
		this.knightsRedo = new ArrayList<Knight>();
		this.visitedRedo = new ArrayList<Boolean[][]>();
		this.boardsRedo = new ArrayList<Board>();
		this.ioRedo = new ArrayList<Integer>();
		this.allMovesRedo = new ArrayList<ArrayList<Point>>();
		
		this.board1 = new Board();
		this.knight = new Knight(7, 0, board1, "White");
		this.board1.add(this.knight);
		this.io.setMode(InputAndOutput.LABEL);
		this.io.setOutputField("Welcome to Knight Tour game.");
		this.io.setOutputField("Click on the block you would like to move to.");
		JButton buttontemp = new JButton();
		for (int i = SIZE-1; i >= 0; i--) 
		{
			for (int j = 0; j < SIZE; j++) 
			{
				visited[i][j] = false;
				buttons[i][j].setBackground(buttontemp.getBackground());
			}
		}
		visited[7][0] = true;
		this.io.setOutputField("Welcome to Knight Tour game.");
		this.io.setOutputField("You may select the help manu for additional information.");
		this.print();
	}




	/**
	 * Repeats a step that was made and was previously undo'ed.
	 */
	public void redo() {
		
		if(this.moveNumberRedo>0)
		{
			if(moveNumber<0)
			{
				this.moveNumber = 0;
				
			}
			this.moveNumberRedo--;
			this.board1 = this.boardsRedo.get(moveNumberRedo);
			this.knight = this.knightsRedo.get(moveNumberRedo);
			this.visited = this.visitedRedo.get(moveNumberRedo);
			this.allMoves = this.allMovesRedo.get(moveNumberRedo);
			this.io.setMode(3);
			this.io.setOutputField("Undo is successful!!");
			this.io.setOutputField("Please select a destinations");
			if(this.won())
			{
				this.io.setMode(InputAndOutput.LABEL_AND_BUTTONS);
				this.io.addButtons(yesAndNo);
				this.io.setOutputField(" ");
				this.io.setOutputField("Congratulations, you won! Play again?");
				this.io.setVisible(true);
				for (int x = SIZE-1; x >= 0; x--) 
				{
					for (int y = 0; y < SIZE; y++)
					{buttons[x][y].setBackground(Color.white);}
				}
			}
			else if(!(this.hasMoves())){
				this.io.setMode(InputAndOutput.LABEL_AND_BUTTONS);
				this.io.addButtons(yesAndNo);
				this.io.setOutputField("You are trapped! Play again?");
				this.io.setVisible(true);
				
			}
			this.io.setVisible(true);
			JButton tempbutton = new JButton();
			for(int x=0; x<GraphicalKnightsTour.SIZE; x++)
			{
				for(int y=0; y<GraphicalKnightsTour.SIZE; y++)
				{
					this.buttons[x][y].setEnabled(true);
					this.buttons[x][y].setBackground(tempbutton.getBackground());
				}
			}
			
			this.moveNumber++;
			if(this.boardsUndo.size()==0)
			{
				this.moveNumber = 0;
			}
			this.boardsUndo.add(this.moveNumber, this.boardsRedo.get(moveNumberRedo));
			this.knightsUndo.add(this.moveNumber, this.knightsRedo.get(moveNumberRedo));
			this.visitedUndo.add(this.moveNumber, this.visitedRedo.get(moveNumberRedo));
			this.ioUndo.add(this.moveNumber, this.ioRedo.get(moveNumberRedo));
			this.allMovesUndo.add(this.moveNumber, this.allMovesRedo.get(moveNumberRedo));
			
			
			this.boardsRedo.remove(moveNumberRedo);
			this.knightsRedo.remove(moveNumberRedo);
			this.visitedRedo.remove(moveNumberRedo);
			this.ioRedo.remove(moveNumberRedo);
			this.allMovesRedo.remove(moveNumberRedo);
			if(moveNumberRedo==0)
			{
				this.boardsRedo = new ArrayList<Board>();
				this.knightsRedo = new ArrayList<Knight>();
				this.visitedRedo = new ArrayList<Boolean[][]>();
				this.ioRedo = new ArrayList<Integer>();
				this.allMovesRedo = new ArrayList<ArrayList<Point>>();
			}
			this.print();
		}else
		{
			this.io.setOutputField("No more redo move possible.");
			if(this.won())
			{
				this.io.setOutputField("You are trapped! Play again?");
			}else if(!(this.hasMoves()))
			{
				this.io.setOutputField("You are trapped! Play again?");
			}
		}
		if(this.boardsUndo.size()==0)
		{
			this.moveNumber = 0;
		}
		
	}



	/**
	 * Returns the game to the previous state. It undo's the last step and
	 * saves it as a redo step
	 */
	public void undo() {
		
		if(this.moveNumber>0)
		{
			
			this.saveCurrentState();
			if(this.boardsRedo.size()==0)
			{
				this.moveNumberRedo = 0;
			}

			this.boardsRedo.add(moveNumberRedo, this.boardsUndo.get(moveNumber));
			this.knightsRedo.add(moveNumberRedo, this.knightsUndo.get(moveNumber));
			this.visitedRedo.add(moveNumberRedo, this.visitedUndo.get(moveNumber));
			this.ioRedo.add(moveNumberRedo, this.ioUndo.get(moveNumber));
			this.allMovesRedo.add(moveNumberRedo, this.allMovesUndo.get(moveNumber));
			
			this.moveNumberRedo++;
			this.boardsUndo.remove(moveNumber);
			this.knightsUndo.remove(moveNumber);
			this.visitedUndo.remove(moveNumber);
			this.ioUndo.remove(moveNumber);
			this.allMovesUndo.remove(moveNumber);
			this.moveNumber--;
			
			
			this.board1 = this.boardsUndo.get(moveNumber);
			this.knight = this.knightsUndo.get(moveNumber);
			this.visited = this.visitedUndo.get(moveNumber);
			this.allMoves = this.allMovesUndo.get(moveNumber);
			this.io.setMode(3);
			this.io.setOutputField("Undo is successful!!");
			this.io.setOutputField("Please select a destinations.");
			this.io.setVisible(true);
			JButton tempbutton = new JButton();
			for(int x=0; x<GraphicalKnightsTour.SIZE; x++)
			{
				for(int y=0; y<GraphicalKnightsTour.SIZE; y++)
				{
					this.buttons[x][y].setEnabled(true);
					this.buttons[x][y].setBackground(tempbutton.getBackground());
				}
			}
			this.print();
			if(moveNumber==0)
			{
				this.boardsUndo = new ArrayList<Board>();
				this.knightsUndo = new ArrayList<Knight>();
				this.visitedUndo = new ArrayList<Boolean[][]>();
				this.ioUndo = new ArrayList<Integer>();
				this.allMovesUndo = new ArrayList<ArrayList<Point>>();
				this.saveCurrentState();
				moveNumber = 0;
			}
		}else
		{
			this.moveNumber = -1;
			this.io.setOutputField("No more undo move possible.");
			this.io.setOutputField("Welcome to Knight Tour Game.");
		}
		if(this.boardsRedo.size()==0)
		{
			this.moveNumberRedo = 0;
		}
	}	
	
}
